﻿/*
 * Author:		shikezheng
 * Create date: 2011-06-15
 * Description:	密封类。此类中函数利用反射，生成DAL的实例
 * */
using System;
using System.Reflection;
using System.Configuration;

namespace YhmOA.Common
{
    public sealed class DataProvider
    {
        /// <summary>
        /// Entity Framework程序集
        /// </summary>
        private static readonly string EFAssemblyPath = ConfigurationManager.AppSettings["EFDAL"];
        /// <summary>
        /// ADO.NET程序集
        /// </summary>
        private static readonly string AssemblyPath = ConfigurationManager.AppSettings["DAL"];

        #region CreateObject

        /// <summary>
        /// 不使用缓存加载程序集并创建类的实例
        /// </summary>
        /// <param name="assemblyPath">程序集路径</param>
        /// <param name="classNamespace">类名和命名空间</param>
        /// <returns>类的实例</returns>
        private static object createObjectNoCache(string assemblyPath, string classNamespace)
        {
            try
            {
                object objType = Assembly.Load(assemblyPath).CreateInstance(classNamespace);
                return objType;
            }
            catch(System.Exception ex)
            {
                Log.Error(ex.Message);
                return null;
            }

        }
        
        /// <summary>
        /// 使用缓存加载程序集并创建类的实例
        /// </summary>
        /// <param name="assemblyPath">程序集路径</param>
        /// <param name="classNamespace">类名和命名空间</param>
        /// <returns>类的实例</returns>
        private static object createObject(string assemblyPath, string classNamespace)
        {
            object objType = DataCache.GetCache(classNamespace);
            if (objType == null)
            {
                try
                {
                    objType = Assembly.Load(assemblyPath).CreateInstance(classNamespace, false);
                    DataCache.SetCache(classNamespace, objType);// 写入缓存
                }
                catch (System.Exception ex)
                {
                    Log.Error(ex.Message);
                    return null;
                }
            }
            return objType;
        }

        /// <summary>
        /// 使用缓存加载程序集并创建泛型类的实例
        /// </summary>
        /// <param name="assemblyPath">程序集路径</param>
        /// <param name="classNamespace">类名和命名空间</param>
        /// <param name="type">泛型类型参数</param>
        /// <returns>类的实例</returns>
        private static object createGObjectNoCache(string assemblyPath, string classNamespace, Type gtype)
        {
            try
            {
                Type type = Assembly.Load(assemblyPath).GetType(classNamespace, true, false).MakeGenericType(gtype);
                object objType = Activator.CreateInstance(type);
                return objType;
            }
            catch (System.Exception ex)
            {
                Log.Error(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// 使用缓存加载程序集并创建泛型类的实例
        /// </summary>
        /// <param name="assemblyPath">程序集路径</param>
        /// <param name="classNamespace">类名和命名空间</param>
        /// <param name="type">泛型类型参数</param>
        /// <returns>类的实例</returns>
        private static object createGObject(string assemblyPath, string classNamespace, Type gtype)
        {
            object objType = DataCache.GetCache(classNamespace);
            if (objType == null)
            {
                try
                {
                    Type type = Assembly.Load(assemblyPath).GetType(classNamespace, true, false).MakeGenericType(gtype);
                    objType = Activator.CreateInstance(type);
                    DataCache.SetCache(classNamespace, objType);// 写入缓存
                }
                catch (System.Exception ex)
                {
                    Log.Error(ex.Message);
                    return null;
                }
            }
            return objType;
        }
        #endregion

        /// <summary>
        /// 根据接口类型得到Entity Framework的数据访问
        /// </summary>
        /// <typeparam name="T">接口类型</typeparam>
        /// <returns>Entity Framework的数据访问</returns>
        public static T GetEFDal<T>()
        {
            Type type = typeof(T);
            string classNamespace = String.Format("{0}.{1}", EFAssemblyPath, type.Name.Substring(1, type.Name.Length - 1));
            object objType = createObjectNoCache(EFAssemblyPath.Replace(".", ""), classNamespace);
            return (T)objType;
        }

        /// <summary>
        /// 根据接口类型得到ADO.NET的数据访问
        /// </summary>
        /// <typeparam name="T">接口类型</typeparam>
        /// <returns>ADO.NET的数据访问</returns>
        public static T GetDal<T>()
        {
            Type type = typeof(T);
            string classNamespace = String.Format("{0}.{1}", AssemblyPath, type.Name.Substring(1, type.Name.Length - 1));
            object objType = createObject(AssemblyPath.Replace(".", ""), classNamespace);
            return (T)objType;
        }

        /// <summary>
        /// 根据接口类型得到Entity Framework的泛型数据访问
        /// </summary>
        /// <typeparam name="T">接口类型</typeparam>
        /// <returns>Entity Framework的泛型数据访问</returns>
        public static T GetGEFDal<T>()
        {
            //泛型的类型
            Type type = typeof(T);
            //泛型类型参数的类型
            Type gtype;
            if (typeof(T).GetGenericArguments().Length == 1)
                gtype = typeof(T).GetGenericArguments()[0];
            else
                gtype = null;

            string classNamespace = String.Format("{0}.{1}", EFAssemblyPath, type.Name.Substring(1, type.Name.Length - 1));

            object objType;
            if (gtype != null)
                objType = createGObjectNoCache(EFAssemblyPath.Replace(".", ""), classNamespace, gtype);
            else
                objType = null;

            return (T)objType;
        }
    }
}
